package com.app.backend.activiti.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.app.backend.activiti.entity.ActBiz;
import com.app.backend.activiti.entity.ActProcess;
import com.app.backend.activiti.service.ActBusinessService;
import com.app.backend.activiti.service.ActProcessService;
import com.app.backend.activiti.vo.ActPage;
import com.app.backend.activiti.vo.HistoricProcessInsVo;
import com.app.backend.activiti.vo.ProcessInsVo;
import com.app.backend.activiti.vo.ProcessNodeVo;
import com.app.backend.base.service.UserService;
import com.app.backend.common.constant.ActConstant;
import com.app.backend.common.response.BaseResponse;
import com.app.backend.common.vo.PageVo;
import com.app.backend.common.vo.SearchVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricIdentityLink;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @program: ActProcessInsController
 * @description:
 * @author: Zhun.Xiao
 * @create: 2020-02-27 10:45
 **/


@Slf4j
@RestController
@Api("流程实例管理")
@RequestMapping("/api/v1/act/processInstance")
@Transactional
public class ActProcessInsController {
    @Autowired
    private RuntimeService runtimeService;


    @Autowired
    private HistoryService historyService;

    @Autowired
    private ActProcessService actProcessService;
    @Autowired
    private UserService userService;

    @Autowired
    private TaskService taskService;


    private ActBusinessService actBusinessService;

    @PostMapping("/getRunningProcessIns")
    @ApiOperation("获取运行中的流程实例. 通过流程key/name做筛选")
    public BaseResponse getRunningProcessIns(@RequestParam(required = false) String name,
                                             @RequestParam(required = false) String key,
                                             PageVo pageVo) {
        ActPage<ProcessInsVo> page = new ActPage<>();
        List<ProcessInsVo> list = new ArrayList<>();
        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery()
                .orderByProcessDefinitionId()
                .desc();

        if (StrUtil.isNotBlank(name)) {
            query.processInstanceNameLike("%" + name + "%");
        }
        if (StrUtil.isNotBlank(key)) {
            query.processDefinitionKey(key);
        }
        page.setTotalElements(query.count());
        int first = (pageVo.getPageNumber() - 1) * pageVo.getPageSize();
        List<ProcessInstance> processInstances = query.listPage(first, pageVo.getPageSize());
        processInstances.forEach(e -> list.add(new ProcessInsVo(e)));

        list.forEach(e -> {
            List<HistoricIdentityLink> hisLinks = historyService.getHistoricIdentityLinksForProcessInstance(e.getId());
            hisLinks.forEach(link -> {
                if ("starter".equals(link.getType()) && StrUtil.isNotEmpty(link.getUserId())) {
                    e.setApplyer(userService.get(link.getUserId()).getUsername());
                }
            });

            // 关联当前任务
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(e.getProcInstId()).list();
            if (taskList != null && taskList.size() == 1) {
                e.setCurrTaskName(taskList.get(0).getName());
            } else if (taskList != null && taskList.size() > 1) {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < taskList.size() - 1; i++) {
                    sb.append(taskList.get(i).getName() + "、");
                }
                sb.append(taskList.get(taskList.size() - 1).getName());
                e.setCurrTaskName(sb.toString());
            }
            // 关联流程表单路由
            ActProcess actProcess = actProcessService.get(e.getProcDefId());
            if (actProcess != null) {
                e.setRouteName(actProcess.getRouteName());
            }
            // 关联业务表id
            ActBiz actBiz = actBusinessService.get(e.getBusinessKey());
            if (actBiz != null) {
                e.setTableId(actBiz.getTableId());
            }

        });

        page.setContent(list);
        return new BaseResponse(page);
    }


    @PostMapping("/getFinishedProcessIns")
    @ApiOperation("获取结束的实例")
    public BaseResponse getFinishedProcessIns(@RequestParam(required = false) String name,
                                              @RequestParam(required = false) String key,
                                              PageVo pageVo,
                                              SearchVo searchVo) {

        ActPage<HistoricProcessInsVo> page = new ActPage<HistoricProcessInsVo>();
        List<HistoricProcessInsVo> list = new ArrayList<>();
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().finished().
                orderByProcessInstanceEndTime().desc();
        if (StrUtil.isNotBlank(name)) {
            query.processInstanceNameLike("%" + name + "%");
        }
        if (StrUtil.isNotBlank(key)) {
            query.processDefinitionKey(key);
        }
        if (StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) {
            Date start = DateUtil.parse(searchVo.getStartDate());
            Date end = DateUtil.parse(searchVo.getEndDate());
            query.finishedAfter(start);
            query.finishedBefore(DateUtil.endOfDay(end));
        }

        page.setTotalElements(query.count());
        int first = (pageVo.getPageNumber() - 1) * pageVo.getPageSize();
        List<HistoricProcessInstance> processInstanceList = query.listPage(first, pageVo.getPageSize());
        processInstanceList.forEach(e -> {
            list.add(new HistoricProcessInsVo(e));
        });
        list.forEach(e -> {
            List<HistoricIdentityLink> identityLinks = historyService.getHistoricIdentityLinksForProcessInstance(e.getId());
            for (HistoricIdentityLink hik : identityLinks) {
                // 关联发起人
                if ("starter".equals(hik.getType()) && StrUtil.isNotBlank(hik.getUserId())) {
                    e.setApplyer(userService.get(hik.getUserId()).getUsername());
                }
            }
            // 关联流程表单路由
            ActProcess actProcess = actProcessService.get(e.getProcDefId());
            if (actProcess != null) {
                e.setRouteName(actProcess.getRouteName());
            }
            // 关联业务表id和结果
            ActBiz actBusiness = actBusinessService.get(e.getBusinessKey());
            if (actBusiness != null) {
                e.setTableId(actBusiness.getTableId());
                String reason = e.getDeleteReason();
                if (reason == null) {
                    //通过
                    e.setResult(ActConstant.RESULT_PASS);
                } else if (reason.contains(ActConstant.CANCEL_PRE)) {
                    //撤回
                    e.setResult(ActConstant.RESULT_CANCEL);
                } else if (ActConstant.BACKED_FLAG.equals(reason)) {
                    //驳回
                    e.setResult(ActConstant.RESULT_REJECT);
                } else if (reason.contains(ActConstant.DELETE_PRE)) {
                    //删除
                    e.setResult(ActConstant.RESULT_DELETED);
                } else {
                    e.setResult(ActConstant.RESULT_PASS);
                }
            }
        });
        page.setContent(list);
        return new BaseResponse(page);
    }


    @PostMapping(value = "/getFirstNode")
    @ApiOperation(value = "通过流程定义id获取第一个任务节点")
    public BaseResponse getFirstNode(@ApiParam("流程定义id") @RequestParam String procDefId) {
        ProcessNodeVo node = actProcessService.getFirstNode(procDefId);
        return new BaseResponse(node);
    }

    @PostMapping(value = "/getNextNode")
    @ApiOperation(value = "通过当前节点定义id获取下一个节点")
    public BaseResponse getNextNode(@ApiParam("当前流程定义id") @RequestParam String procDefId,
                                    @ApiParam("当前节点定义id") @RequestParam String currActId) {
        ProcessNodeVo node = actProcessService.getNextNode(procDefId, currActId);
        return new BaseResponse(node);
    }

    @PostMapping(value = "/getNode")
    @ApiOperation(value = "通过节点nodeId获取审批人")
    public BaseResponse getNode(@ApiParam("节点nodeId") @RequestParam String nodeId) {
        ProcessNodeVo node = actProcessService.getNode(nodeId);
        return new BaseResponse(node);
    }


}